#include "media_souce.h"
#include <random>

using namespace VLRTSP;

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 16:17:58
 * 
 * 构造函数
 */
MediaSource::MediaSource(): handleThread([this](std::shared_ptr<MediaSourceData> data) {
	this->_onRecvBuffer(data);
}), syncCode(1), seqCode(0, UINT16_MAX) {
	this->isAttached = false;

	std::random_device rd;
	this->rtpHeader.csrc = 0;
	this->rtpHeader.extension = 0;
	this->rtpHeader.padding = 0;
	this->rtpHeader.version = RTP_VERSION;
	this->rtpHeader.marker = 0;
	this->rtpHeader.timestamp = htonl(rd());
	this->rtpHeader.ssrc = htonl(rd());
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-13 16:18:03
 * 
 * 析构函数
 */
MediaSource::~MediaSource() {

}

/**
 * @Author: CimZzz
 * @Date: 2022-01-14 14:27:42
 * 
 * 添加 RTP 帧发送回调
 * @param callback RTP 帧发送回调
 * @return 回调编号
 */
uint32_t MediaSource::addFrameSendCallback(RTPFrameSendCallback callback) {
	std::lock_guard< std::mutex > lock(this->callbackMutex);
	uint32_t code = this->syncCode.nextCode();
	this->callbackMap[code] = callback;
	return code;
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-14 14:33:04
 * 
 * 移除 RTP 帧发送回调
 * @param code 回调编号
 */
void MediaSource::removeFrameSendCallback(uint32_t code) {
	std::lock_guard< std::mutex > lock(this->callbackMutex);
	auto iter = this->callbackMap.find(code);
	if(iter != this->callbackMap.end()) {
		this->callbackMap.erase(code);
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-07 16:54:49
 * 
 * 发送媒体资源数据
 * @param sourceData 媒体资源数据
 * 
 */
void MediaSource::sendFrame(MediaSourceData* sourceData) {
	this->handleThread.send(std::shared_ptr<MediaSourceData>(sourceData));
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-13 16:53:13
 * 
 * 获取媒体资源 Id
 * @return 媒体资源 Id
 */
uint32_t MediaSource::getSouceId() {
	return this->sourceId;
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-14 15:34:30
 * 
 * 填充 RTP 头部
 * @param buffer RTP 帧字节缓冲区
 * @param timestamp 帧时间戳
 * @param isLast 如果是最后一个包，该值为 true(适用于分包处理)
 */
void MediaSource::fillRTPHeader(Buffer* buffer, uint32_t timestamp, bool isLast) {
	if(isLast) {
		this->rtpHeader.marker = 1;
	} else {
		this->rtpHeader.marker = 0;
	}

	this->rtpHeader.payload = (uint8_t)this->getPayloadType();
	this->rtpHeader.timestamp = htonl(timestamp);
	this->rtpHeader.seq = htons(this->seqCode.getCode());
	this->seqCode.nextCode();
	// 插入 RTP 头部数据
	// 留出 TCP 头部空白
	buffer->appendBuffer((uint8_t*)&this->rtpHeader, 0, RTP_HEADER_LENGTH);
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-10 15:53:33
 * 
 * 发送 RTP 帧
 * @param frame RTP 帧指针
 */
void MediaSource::sendRTPFrame(std::shared_ptr<RTPFrame> frame) {
	std::lock_guard< std::mutex > lock(this->callbackMutex);
	// 遍历 Map 发送数据
	if(this->callbackMap.empty()) {
		return;
	}

	for(auto iter = this->callbackMap.begin() ; iter != this->callbackMap.end() ; iter ++) {
		iter->second(frame);
	}
}

/**
 * @Author: CimZzz
 * @Date: 2022-01-07 11:47:23
 * 
 * 贴附上 MediaSession
 * @param session 媒体会话
 * @param sourceId 媒体资源 Id
 */
void MediaSource::_attachSession(MediaSession* session, uint32_t sourceId) {
	this->mediaSession = session;
	this->sourceId = sourceId;
	this->isAttached = true;
	// 启动内部消息队列
	this->handleThread.start();
}


/**
 * @Author: CimZzz
 * @Date: 2022-01-14 14:09:05
 * 
 * 接收到消息队列发送来的数据
 * @param data 媒体资源数据
 */
void MediaSource::_onRecvBuffer(std::shared_ptr<MediaSourceData>& data) {
	this->onHandleDataBuffer(data);
}